"""
成绩管理模块 - 权限控制
"""
from rest_framework import permissions
from django.utils import timezone


class CanManageGradingStandard(permissions.BasePermission):
    """
    可以管理评分标准的权限
    """

    def has_permission(self, request, view):
        """检查是否有权限访问"""
        if not request.user.is_authenticated:
            return False

        # 管理员和教师可以管理评分标准
        return request.user.is_admin_user or request.user.is_teacher

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以管理所有评分标准
        if request.user.is_admin_user:
            return True

        # 教师只能管理自己创建的评分标准
        return obj.creator == request.user


class CanManageGradeSheet(permissions.BasePermission):
    """
    可以管理成绩单的权限
    """

    def has_permission(self, request, view):
        """检查是否有权限访问"""
        if not request.user.is_authenticated:
            return False

        # 管理员和教师可以管理成绩单
        return request.user.is_admin_user or request.user.is_teacher

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以管理所有成绩单
        if request.user.is_admin_user:
            return True

        # 成绩单创建者可以管理
        if obj.creator == request.user:
            return True

        # 考试创建者或监考教师可以管理
        if obj.examination:
            return (
                obj.examination.creator == request.user or
                obj.examination.supervisors.filter(id=request.user.id).exists()
            )

        # 课程教师可以管理
        if obj.course:
            return obj.course.instructor == request.user

        return False


class CanViewGrades(permissions.BasePermission):
    """
    可以查看成绩的权限
    """

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以查看所有成绩
        if request.user.is_admin_user:
            return True

        # 成绩单创建者可以查看
        if hasattr(obj, 'grade_sheet') and obj.grade_sheet.creator == request.user:
            return True

        # 学生只能查看自己的成绩
        if request.user.is_student:
            if hasattr(obj, 'student'):
                return obj.student == request.user
            if hasattr(obj, 'grades'):
                return obj.grades.filter(student=request.user).exists()

        # 教师可以查看自己管理或监考的考试的成绩
        if request.user.is_teacher:
            if hasattr(obj, 'grade_sheet'):
                grade_sheet = obj.grade_sheet
                # 检查是否是成绩单创建者
                if grade_sheet.creator == request.user:
                    return True

                # 检查是否是考试创建者或监考教师
                if grade_sheet.examination:
                    return (
                        grade_sheet.examination.creator == request.user or
                        grade_sheet.examination.supervisors.filter(id=request.user.id).exists()
                    )

                # 检查是否是课程教师
                if grade_sheet.course:
                    return grade_sheet.course.instructor == request.user

            # 如果是成绩单对象
            elif hasattr(obj, 'examination'):
                return (
                    obj.creator == request.user or
                    obj.supervisors.filter(id=request.user.id).exists()
                )
            elif hasattr(obj, 'course'):
                return obj.instructor == request.user

        return False


class CanManageAppeals(permissions.BasePermission):
    """
    可以管理申诉的权限
    """

    def has_permission(self, request, view):
        """检查是否有权限访问"""
        if not request.user.is_authenticated:
            return False

        # 管理员和教师可以管理申诉
        return request.user.is_admin_user or request.user.is_teacher

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以管理所有申诉
        if request.user.is_admin_user:
            return True

        # 成绩单创建者可以管理相关申诉
        if obj.grade.grade_sheet.creator == request.user:
            return True

        # 考试创建者或监考教师可以管理
        examination = obj.grade.exam_session.examination
        return (
            examination.creator == request.user or
            examination.supervisors.filter(id=request.user.id).exists()
        )


class CanCreateStatistics(permissions.BasePermission):
    """
    可以创建统计的权限
    """

    def has_permission(self, request, view):
        """检查是否有权限访问"""
        if not request.user.is_authenticated:
            return False

        # 管理员和教师可以创建统计
        return request.user.is_admin_user or request.user.is_teacher


class CanAccessGradeSheet(permissions.BasePermission):
    """
    可以访问成绩单的综合权限
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 列表视图权限在get_queryset中控制
        if view.action == 'list':
            return True

        # 创建操作需要教师权限
        if view.action == 'create':
            return request.user.is_admin_user or request.user.is_teacher

        return True

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        if view.action == 'retrieve':
            return CanViewGrades().has_object_permission(request, view, obj)
        elif view.action in ['update', 'partial_update', 'destroy', 'calculate_grades',
                           'review', 'publish', 'batch_adjust_grades', 'export_grades']:
            return CanManageGradeSheet().has_object_permission(request, view, obj)
        elif view.action in ['ranking_analysis']:
            return CanViewGrades().has_object_permission(request, view, obj)

        return False


class CanAccessGrade(permissions.BasePermission):
    """
    可以访问成绩记录的综合权限
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 列表视图权限在get_queryset中控制
        if view.action == 'list':
            return True

        return True

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        if view.action == 'retrieve':
            return CanViewGrades().has_object_permission(request, view, obj)
        elif view.action in ['update', 'partial_update', 'destroy', 'add_component', 'adjust_score']:
            return CanManageGradeSheet().has_object_permission(request, view, obj)

        return False


class CanAccessAppeal(permissions.BasePermission):
    """
    可以访问申诉的综合权限
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 列表视图权限在get_queryset中控制
        if view.action == 'list':
            return True

        # 创建申诉，学生可以创建自己的申诉
        if view.action == 'create':
            return True

        return True

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        if view.action == 'retrieve':
            return CanViewGrades().has_object_permission(request, view, obj)
        elif view.action in ['update', 'partial_update', 'destroy', 'accept', 'reject']:
            return CanManageAppeals().has_object_permission(request, view, obj)
        elif view.action in ['start_review']:
            # 学生可以开始审核自己的申诉（这个逻辑可能需要调整）
            return obj.student == request.user

        return False


class CanAccessStatistics(permissions.BasePermission):
    """
    可以访问统计的综合权限
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 学生不能直接访问统计
        if request.user.is_student:
            return False

        # 列表视图权限在get_queryset中控制
        if view.action == 'list':
            return True

        # 创建统计需要管理员或教师权限
        if view.action == 'create':
            return request.user.is_admin_user or request.user.is_teacher

        return True

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以访问所有统计
        if request.user.is_admin_user:
            return True

        # 统计创建者可以访问
        if obj.creator == request.user:
            return True

        # 相关考试创建者可以访问
        if obj.examination and obj.examination.creator == request.user:
            return True

        # 相关课程教师可以访问
        if obj.course and obj.course.instructor == request.user:
            return True

        return False


class IsGradeSheetPublished(permissions.BasePermission):
    """
    检查成绩单是否已发布
    """

    def has_object_permission(self, request, view, obj):
        """检查成绩单状态"""
        # 学生只能访问已发布的成绩单
        if request.user.is_student:
            return obj.status == 'published'

        # 教师和管理员可以访问所有状态的成绩单
        return True


class IsAppealOwnerOrCanManage(permissions.BasePermission):
    """
    申诉所有者或有管理权限
    """

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 申诉学生可以查看自己的申诉
        if obj.student == request.user:
            return True

        # 有管理权限的用户可以管理申诉
        return CanManageAppeals().has_object_permission(request, view, obj)


class CanExportGrades(permissions.BasePermission):
    """
    可以导出成绩的权限
    """

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以导出所有成绩
        if request.user.is_admin_user:
            return True

        # 成绩单创建者可以导出
        if obj.creator == request.user:
            return True

        # 考试创建者或监考教师可以导出
        if obj.examination:
            return (
                obj.examination.creator == request.user or
                obj.examination.supervisors.filter(id=request.user.id).exists()
            )

        # 课程教师可以导出
        if obj.course:
            return obj.course.instructor == request.user

        return False


class CanAdjustGrades(permissions.BasePermission):
    """
    可以调整成绩的权限
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 只有管理员和教师可以调整成绩
        return request.user.is_admin_user or request.user.is_teacher

    def has_object_permission(self, request, view, obj):
        """检查对象权限"""
        # 管理员可以调整所有成绩
        if request.user.is_admin_user:
            return True

        # 成绩单创建者可以调整
        if obj.creator == request.user:
            return True

        # 考试创建者或监考教师可以调整
        if obj.examination:
            return (
                obj.examination.creator == request.user or
                obj.examination.supervisors.filter(id=request.user.id).exists()
            )

        # 课程教师可以调整
        if obj.course:
            return obj.course.instructor == request.user

        return False


class HasGradingAccess(permissions.BasePermission):
    """
    具有成绩管理访问权限的综合检查
    """

    def has_permission(self, request, view):
        """检查基本权限"""
        if not request.user.is_authenticated:
            return False

        # 学生不能进行成绩管理操作
        if request.user.is_student:
            return False

        # 管理员和教师有基本访问权限
        return request.user.is_admin_user or request.user.is_teacher

    def has_object_permission(self, request, view, obj):
        """根据不同的操作检查权限"""
        if hasattr(obj, 'grade_sheet'):
            # 成绩对象
            return CanManageGradeSheet().has_object_permission(request, view, obj.grade_sheet)
        else:
            # 成绩单对象
            return CanManageGradeSheet().has_object_permission(request, view, obj)


class IsAppealInProcessableState(permissions.BasePermission):
    """
    申诉处于可处理状态
    """

    def has_object_permission(self, request, view, obj):
        """检查申诉状态"""
        processable_states = ['pending', 'reviewing']
        return obj.status in processable_states


class IsGradingStandardActive(permissions.BasePermission):
    """
    评分标准是否启用
    """

    def has_object_permission(self, request, view, obj):
        """检查评分标准状态"""
        return obj.is_active